/*
 *    Copyright (c) 2018-2025, nart All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: nart
 */
package com.nai365.nart.operation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nai365.nart.blockchain.dto.TransferDto;
import com.nai365.nart.common.security.util.SecurityUtils;
import com.nai365.nart.operation.config.RabbitmqConfig;
import com.nai365.nart.operation.dto.RecoveryParam;
import com.nai365.nart.operation.entity.RecoveryDetail;
import com.nai365.nart.operation.entity.RecoveryRecord;
import com.nai365.nart.operation.mapper.RecoveryDetailMapper;
import com.nai365.nart.operation.mapper.RecoveryRecordMapper;
import com.nai365.nart.operation.service.OrderService;
import com.nai365.nart.operation.service.ProductService;
import com.nai365.nart.operation.service.RecoveryService;
import com.nai365.nart.order.entity.OrderItem;
import com.nai365.nart.product.entity.SkuInfo;
import com.nai365.nart.product.entity.SpuInfo;
import lombok.AllArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.klock.annotation.Klock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 回收功能服务类
 *
 * @author linco
 * @version 1.0
 * @date 2022-07-22 13:29:36
 * @since 1.0
 */
@Service
@AllArgsConstructor
public class RecoveryServiceImpl extends ServiceImpl<RecoveryRecordMapper, RecoveryRecord> implements RecoveryService {

	private final RecoveryDetailMapper recoveryDetailMapper;

	private final ProductService productService;

	private final RabbitTemplate rabbitTemplate;

	private final OrderService orderService;

	@Override
	public RecoveryRecord getById(Serializable id) {
		RecoveryRecord result = super.getById(id);
		LambdaQueryWrapper<RecoveryDetail> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(RecoveryDetail::getRecordId, id);
		result.setDetailList(recoveryDetailMapper.selectList(queryWrapper));
		return result;
	}

	@Override
	@Klock()
	@Transactional(rollbackFor = Exception.class)
	public RecoveryRecord recovery(RecoveryParam recoveryParam) throws Exception {
		//条件验证
		if (recoveryParam.getSkuIdList() == null || recoveryParam.getSkuIdList().isEmpty()) {
			throw new Exception("待回收藏品不能为空!");
		}
		List<SkuInfo> skuInfoList = productService.findSkuByIds(recoveryParam.getSkuIdList());
		if (skuInfoList.isEmpty()) {
			throw new Exception("查询不到待回收藏品(sku)!");
		}
		for (SkuInfo sku : skuInfoList) {
			if (!Objects.equals(sku.getOwnerId(), SecurityUtils.getUser().getId())) {
				throw new Exception("待回收藏品中存在不属于你的藏品!");
			}
			if (!sku.getAbleRecovery()) {
				throw new Exception("待回收藏品中存在不能回收藏品!");
			}
		}
		SpuInfo spuInfo = productService.findSpuById(recoveryParam.getSpuId());
		if (spuInfo == null) {
			throw new Exception("查询不到待回收藏品(spu)!");
		}
		//获取订单项
		List<OrderItem> orderItemList = orderService.findPayedBySkuIdList(recoveryParam.getSkuIdList());
		BigDecimal totalAmount = orderItemList.stream().map(OrderItem::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
		Map<Long, OrderItem> orderItemMap = orderItemList.stream().collect(Collectors.toMap(OrderItem::getSkuId, a -> a));
		//保存回收记录
		RecoveryRecord recoveryRecord = new RecoveryRecord();
		recoveryRecord.setUserId(SecurityUtils.getUser().getId());
		recoveryRecord.setCopies(skuInfoList.size());
		recoveryRecord.setSpuId(recoveryParam.getSpuId());
		recoveryRecord.setSpuName(spuInfo.getSpuName());
		recoveryRecord.setSpuToken(spuInfo.getToken() + "");
		recoveryRecord.setSpuImage(spuInfo.getChainUrl());
		recoveryRecord.setSpuTxHash(spuInfo.getTxHash());
		recoveryRecord.setStatus(0);
		recoveryRecord.setSpuPublishTime(spuInfo.getChainTime());
		recoveryRecord.setSpuPublishSellTime(spuInfo.getSaleTime());
		recoveryRecord.setSpuPublishSellPrice(spuInfo.getPublishPrice());
		recoveryRecord.setRecoveryAmount(totalAmount);
		this.save(recoveryRecord);
		//保存回收详情
		List<RecoveryDetail> detailList = new ArrayList<>();
		for (SkuInfo sku : skuInfoList) {
			RecoveryDetail recoveryDetail = new RecoveryDetail();
			recoveryDetail.setUserId(SecurityUtils.getUser().getId());
			recoveryDetail.setRecordId(recoveryRecord.getId());
			recoveryDetail.setSkuId(sku.getSkuId());
			recoveryDetail.setSkuName(sku.getSkuName());
			recoveryDetail.setSkuToken(sku.getToken() + "");
			if (StringUtils.isBlank(sku.getSkuDefaultImg())) {
				recoveryDetail.setSkuImage(spuInfo.getChainUrl());
			} else {
				recoveryDetail.setSkuImage(sku.getSkuDefaultImg());
			}
			recoveryDetail.setSkuCode(sku.getSkuCode());
			recoveryDetail.setStatus(0);
			recoveryDetail.setSpuId(recoveryParam.getSpuId());
			recoveryDetail.setOwnerId(sku.getOwnerId());
			recoveryDetail.setOwnerAddress(sku.getOwnerAddress());
			recoveryDetail.setRecoveryAddress("0x49cb0e9a80887e89255e005fc7919b598f5b0851");
			OrderItem orderItem = orderItemMap.get(recoveryDetail.getSkuId());
			if(orderItem!=null){
				recoveryDetail.setRecoveryAmount(orderItem.getRealAmount());
			}
			recoveryDetailMapper.insert(recoveryDetail);
			detailList.add(recoveryDetail);
			sku.setPublishStatus(3);

		}
		productService.updateBatchSkuInfo(skuInfoList);
		recoveryRecord.setDetailList(detailList);
		return recoveryRecord;
	}

	@Override
	public void recoveryChain(Long recordId) {
		LambdaQueryWrapper<RecoveryDetail> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(RecoveryDetail::getRecordId, recordId);
		List<RecoveryDetail> detailList = recoveryDetailMapper.selectList(queryWrapper);
		if (detailList != null && !detailList.isEmpty()) {
			for (RecoveryDetail detail : detailList) {
				TransferDto transferDto = TransferDto.builder()
						.from(detail.getOwnerAddress())
						.to(detail.getRecoveryAddress())
						.copies(1)
						.token(detail.getSkuToken())
						.exchangeName(RabbitmqConfig.BLOCKCHAIN_EXCHANGE)
						.notifyRoute(RabbitmqConfig.RECOVERY_ROUTING_KEY)
						.requestId(detail.getId() + "")
						.build();
				rabbitTemplate.convertAndSend(RabbitmqConfig.BLOCKCHAIN_EXCHANGE, RabbitmqConfig.TRANSFER_ROUTING_KEY, transferDto);
			}
		}
	}
}
